import axios from 'axios';
import { isFunction } from '@vc/utils';
import type { Canceler, AxiosRequestConfig } from 'axios';

let pendingMap = new Map<string, {cancel: Canceler, config: AxiosRequestConfig}>();

export const getPendingUrl = (config: AxiosRequestConfig) => [config.method, config.url].join('&');

export class AxiosCanceler {
  addPending (config: AxiosRequestConfig) {
    this.removePending(config);
    const url = getPendingUrl(config);
    config.cancelToken =
      config.cancelToken ||
      new axios.CancelToken((cancel) => {
        if (!pendingMap.has(url)) {
          pendingMap.set(url, { cancel, config });
        }
      });
  }
  
  removeAllPending (deleteUrl = true) {
    pendingMap.forEach((item) => {
      item.cancel && isFunction(item.cancel) && item.cancel();
    });
    if (deleteUrl) {
      pendingMap.clear();
    }
  }
  
  removePending (config: AxiosRequestConfig) {
    const url = getPendingUrl(config);
    
    if (pendingMap.has(url)) {
      const cancelItem = pendingMap.get(url);
      cancelItem?.cancel && cancelItem.cancel(url);
      pendingMap.delete(url);
    }
  }

  reset (): void {
    pendingMap = new Map<string, {cancel: Canceler, config: AxiosRequestConfig}>();
  }
  
  getAllPending () {
    return pendingMap;
  }
}
